#include "libfactory.h"

int factory_adapt(char *app, char *id, char *target) {
	char * genericFactoryAddress = malloc(256);
	sprintf(genericFactoryAddress, "");

	struct timeval t_start, t_finish, t_elapsed;

	gettimeofday(&t_start, NULL);

	factory_find(target, &genericFactoryAddress);

	gettimeofday(&t_finish, NULL);

	timeval_subtract(&t_elapsed, &t_finish, &t_start);

	fprintf(stderr, "factory.c: findFactories used %.f ms\n", t_elapsed.tv_sec
			* 1000 + t_elapsed.tv_usec / 1.e3);

	if (genericFactoryAddress) {
		fprintf(stderr, "factory.c: found factory at %s\n",
				genericFactoryAddress);

		void *handle;
		char *error;
		void (*func)(char*, char*, char*, char *);
		char * awsm_home;
		config_get_string(&awsm_home, "AWSM_HOME");
		handle = dlopen(strcat(awsm_home, "/build/lib/libgenericFactory.so"),
				RTLD_LAZY);
		if (!handle) {
			fprintf(stderr, "factory.c: dlopen: %s\n", dlerror());
			return 1;
		} else {

			func = dlsym(handle, "factory_adapt");
			if ((error = dlerror()) != NULL) {
				fprintf(stderr, "factory.c: dlsym: %s\n", error);
				return 1;
			}

			(*func)(app, id, target, genericFactoryAddress);
			dlclose(handle);
		}
		return 0;
	} else {
		fprintf(stderr, "factory.c: no factory found\n");
		return 1;
	}
}

int factory_register(char *factoryAddress, char * criteriaXml) {
	struct soap *soap = soap_new();
	char * message;

	char * factory_finder_location;
	config_get_string(&factory_finder_location, "FACTORY_FINDER_LOCATION");

	if (soap_call_ns__register(soap, factory_finder_location, NULL,
			criteriaXml, factoryAddress, &message) != SOAP_OK)
		soap_print_fault(soap, stderr);
	else
		fprintf(stderr, "[soap] %s\n", message);

	soap_destroy(soap);
	soap_end(soap);
	soap_done(soap);
	return 0;
}

int factory_find(char * criteriaXml, char **address) {
	struct soap *soap = soap_new();
	struct ArrayOfString *factories;

	char * factory_finder_location;
	config_get_string(&factory_finder_location, "FACTORY_FINDER_LOCATION");

	if (soap_call_ns__findFactories(soap, factory_finder_location, NULL,
			criteriaXml, &factories) != SOAP_OK) {
		*address = NULL;
		soap_print_fault(soap, stderr);

	} else {
		if (factories->__size) {
			*address = (char *) malloc(1024);
			strcpy(*address, factories->__ptr[0]);
		} else
			*address = NULL;

	}
	soap_destroy(soap);
	soap_end(soap);
	soap_done(soap);
	return 0;
}
